package com.stm.bi.report;

import com.stm.base.dto.vo.DictVO;
import com.stm.base.provider.DictionaryProvider;
import com.stm.bi.core.util.DateUtils;
import com.stm.bi.dto.query.DeptChartQuery;
import com.stm.bi.dto.vo.ProductStyleDataVO;
import com.stm.bi.dto.vo.ProductStyleQtyCardVO;
import com.stm.bi.model.Chart;
import com.stm.framework.core.context.UserHolder;
import com.stm.framework.core.util.FileResourceLoader;
import com.stm.framework.dbcp.JdbcService;
import com.stm.framework.dto.Response;
import com.stm.saas.api.CalendarCycleRemoteService;
import com.stm.saas.api.ProductConfigRemoteService;
import com.stm.saas.constant.DictionaryConstants;
import com.stm.saas.dto.vo.ProductConfigVO;
import com.stm.saas.model.CalendarCycle;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

import static com.stm.bi.constant.IndexConstants.*;
import static com.stm.bi.constant.PlanConstants.TYPE_MONTH;


/**
 * @author liuyx
 * @date 2025/2/14 9:09
 */
@Component
public class StyleTypeQtyChartQueryExe extends AbsChartQueryExe<DeptChartQuery, Chart> {
    @Resource
    private JdbcService jdbcService;

    @Resource
    private CalendarCycleRemoteService calendarCycleRemoteService;

    @Resource
    private DictionaryProvider dictionaryProvider;

    @Resource
    protected ProductConfigRemoteService productConfigRemoteService;


    @Override
    public Chart query(Long orgId, String orgNo, DeptChartQuery query) {
        CalendarCycle cyc = calendarCycleRemoteService.getByOrg().get();
        String cycMonth = DateUtils.getCycMonth(LocalDate.now().toString(), cyc.getDay());

        Response<ProductConfigVO> prodResp = productConfigRemoteService.selectByOrgId(UserHolder.getOrgId());
        String salesDefinition = "dealing";
        if(prodResp != null && prodResp.getData() != null) {
            salesDefinition = prodResp.getData().getSalesDefinition();
        }
        if("delivery".equals(salesDefinition)) {
            salesDefinition = "dealing";
        }


        String selectSql = FileResourceLoader.getResourceAsString("/sql/adsBaseProductMultiSalesGroupBy.sql");
        List<Map> maps = jdbcService.selectList(selectSql, new Object[]{
                orgId,
                query.getDeptId(),
                TYPE_MONTH,
                salesDefinition,
                cycMonth,
                cycMonth,});

        maps.sort(Comparator.comparing((Map m) -> ((BigDecimal) m.get(QTY_FIELD))).reversed());

        //总销量
        double totalQty = maps.stream().map(m -> (BigDecimal) m.get(QTY_FIELD)).filter(Objects::nonNull).mapToDouble(BigDecimal::doubleValue).sum();
        List<DictVO> dicts = dictionaryProvider.selectList(DictionaryConstants.STYLE_CATEGORY);
        Chart chartVO = new Chart();
        chartVO.getItems().add("款式类别销量占比");
        List<List<Object>> data = new ArrayList<>();
        double total = 0;
        Map<String, Double> sumMap = new HashMap<>();
        for (DictVO key : dicts) {
            double sum = maps.stream()
                    .filter(m -> key.getValue().equals(m.get(STYLE_TYPE_FIELD)))
                    .map(m -> (BigDecimal) m.get(QTY_FIELD))
                    .filter(Objects::nonNull)
                    .mapToDouble(BigDecimal::doubleValue)
                    .sum();
            total += sum;
            sumMap.put(key.getValue(), sum);
        }

        for (DictVO key : dicts) {
            double proportion = 0;
            if (total != 0) {
                proportion = 100 * sumMap.get(key.getValue()) / total;
            }
            data.add(Arrays.asList(key.getLabel(), BigDecimal.valueOf(proportion).setScale(2, RoundingMode.HALF_UP), BigDecimal.valueOf(sumMap.get(key.getValue()))));
        }
        data.sort(Comparator.comparing((List<Object> a) -> ((BigDecimal) a.get(2))).reversed());
        chartVO.setDatas(data);

        selectSql = FileResourceLoader.getResourceAsString("/sql/adsBaseProductMultiSales.sql");
        maps = jdbcService.selectList(selectSql, new Object[]{
                orgId,
                query.getDeptId(),
                TYPE_MONTH,
                salesDefinition,
                cycMonth,
                cycMonth});

        Map<String, Map<String, Object>> groupedData = new HashMap<>();
        for (Map map : maps) {
            String styleCode = (String) map.get(STYLE_CODE_FIELD);
            if("-99".equals(styleCode)) {
                continue;
            }

            BigDecimal qty = (BigDecimal) map.get(QTY_FIELD);
            BigDecimal salesAmount = (BigDecimal) map.get(SALES_AMOUNT_FIELD);

            groupedData.putIfAbsent(styleCode, map);
            Map<String, Object> typeData = groupedData.get(styleCode);

            typeData.putIfAbsent(QTY_FIELD, BigDecimal.ZERO);
            typeData.putIfAbsent(SALES_AMOUNT_FIELD, BigDecimal.ZERO);

            BigDecimal currentQty = (BigDecimal) typeData.get(QTY_FIELD);
            BigDecimal currentSalesAmount = (BigDecimal) typeData.get(SALES_AMOUNT_FIELD);

            typeData.put(QTY_FIELD, currentQty.add(qty));
            typeData.put(SALES_AMOUNT_FIELD, currentSalesAmount.add(salesAmount));

            groupedData.put(styleCode, typeData);
        }

        List<Map.Entry<String, Map<String, Object>>> sortedGroupedData = new ArrayList<>(groupedData.entrySet());
        sortedGroupedData.sort((entry1, entry2) -> {
            BigDecimal qty1 = (BigDecimal) entry1.getValue().get(QTY_FIELD);
            BigDecimal qty2 = (BigDecimal) entry2.getValue().get(QTY_FIELD);
            return qty2.compareTo(qty1);
        });

        List<Map<String, Object>> res = sortedGroupedData.stream()
                .limit(5)
                .map(Map.Entry::getValue)
                .collect(Collectors.toList());


        List<ProductStyleDataVO> tableData = new ArrayList<>();
        for (Map map : res) {
            BigDecimal qty = (BigDecimal) map.get(QTY_FIELD);

            ProductStyleDataVO productStyleDataVO = new ProductStyleDataVO();
            productStyleDataVO.setName((String) map.get(STYLE_NAME_FIELD))
                    .setType(dicts.stream()
                            .filter(d -> Objects.equals(d.getValue(), map.get(STYLE_TYPE_FIELD)))
                            .findAny().orElse(new DictVO()).getLabel());
            productStyleDataVO.setSales((BigDecimal) map.get(SALES_AMOUNT_FIELD))
                    .setQty(qty);

            if (totalQty != 0) {
                productStyleDataVO.setQtyProportion(BigDecimal.valueOf(100 * qty.doubleValue() / totalQty).setScale(2, RoundingMode.HALF_UP));
            }

            tableData.add(productStyleDataVO);
        }

        ProductStyleQtyCardVO productStyleQtyCardVO = new ProductStyleQtyCardVO();
        productStyleQtyCardVO.setTotal(BigDecimal.valueOf(total).setScale(2, RoundingMode.HALF_UP));
        productStyleQtyCardVO.setTableData(tableData);
        chartVO.setExtend(productStyleQtyCardVO);

        return chartVO;
    }

    @Override
    public String getReportName() {
        return "商品款式销量";
    }
}
